#include "defines.h"
#include "timer.h"
#include "intr.h"
#include "kernel.h"
#include "kozos.h"
#include "kernel.h"

#define TCR8_2   ((volatile uint8 *) 0xffff90)
#define TCR8_3   ((volatile uint8 *) 0xffff91)
#define TCORA    ((volatile uint16 *) 0xffff94)
#define TCNT8    ((volatile uint16 *) 0xffff98)
#define TCSR8_2  ((volatile uint8 *) 0xffff92)
#define TCSR8_3  ((volatile uint8 *) 0xffff93)

static uint32 systime = 0;

uint32 get_systime()
{
    return systime;
}

static void alarm_task()
{
    int i;
    for (i = 0; i < THREAD_NUM; i++) {
        kz_thread *p = &threads[i];
        if (p->flags & THREAD_WAITALARM) {
            if (p->alarm_count) {
                p->alarm_count--;
            } else {
                p->flags &= ~THREAD_WAITALARM;
                thread_wakeup(p);
            }
        }
    }
}

// 0xffff?? のビット操作
#define BSET(ADDR, BIT)  asm volatile ("bset %0,@%c1:8" :: "i" (BIT), "i" (ADDR))
#define BCLR(ADDR, BIT)  asm volatile ("bclr %0,@%c1:8" :: "i" (BIT), "i" (ADDR))

static void timer_intr()
{
//    *TCSR8_3 &= ~0x40;
    BCLR(TCSR8_3, 6);
    systime++;
    alarm_task();
}

void timer_init()
{
#if TICK_PER_SEC != 5
#error TICK_PER_SEC must be 5
#endif
    /* 1/5秒ごとに割り込み */
    sys_setintr(SOFTVEC_TYPE_T8INTR_23, timer_intr);
    *TCR8_2 = 0x00;
    *TCR8_3 = 0x4c;
    *TCORA  = 0xf9f9;
    *TCNT8  = 0;
    *TCSR8_3 &= 0x00;
    *TCR8_2 = 0x0a;
}

int set_alarm(kz_thread *thp, uint32 tick)
{
    thp->flags |= THREAD_WAITALARM;
    thp->alarm_count = tick;
    return 0;
}
